// 导入axios
import axios from "axios"
// 导入axios实例类型
import type { AxiosInstance, AxiosRequestConfig, AxiosResponse, AxiosError } from "axios"
// axioscancle
import { AxiosCanceler, pendingMap, getPendingUrl } from "./axiosCancel"
// 进度条插件
import NProgress from "@/config/nprogress"
// antd message组件
import { message } from "antd"
// 引入axios封装参数
import { baseURL, timeout } from "./config"
// axios请求返回数据ts类型
import { ResultData } from "./typings/common"
// axios封装参数
const config = {
	baseURL,
	timeout,
}
let _config = {}
// 初始化一个axioscancel
const axiosCancel = new AxiosCanceler()
// 封装axios
class HyAxios {
	service: AxiosInstance
	constructor(config: AxiosRequestConfig) {
		// 封装后axios实例
		this.service = axios.create(config)
		// 请求拦截器
		this.service.interceptors.request.use(
			(config) => {
				NProgress.start()
				// 保存config
				_config = config
				// 获取cancel
				const cancel = pendingMap.get(getPendingUrl(config))
				if (cancel) {
					// 有就调用cancel
					cancel()
				}

				// 将当前请求添加到 pending 中
				axiosCancel.addPending(config)

				return config
			},
			(err: AxiosError) => {
				return Promise.reject(err)
			},
		)

		// 响应拦截器
		this.service.interceptors.response.use(
			(response: AxiosResponse) => {
				NProgress.done()
				// * 在请求结束后，移除本次请求(关闭loading)
				axiosCancel.removePending(_config)
				return response.data
			},
			(err: AxiosError) => {
				message.error(err.message)
				return Promise.reject(err)
			},
		)
	}

	request<T>(config: AxiosRequestConfig) {
		return this.service.request<any, T>(config)
	}

	get<T, K>(url: string, pramas?: K, _object = {}): Promise<ResultData<T>> {
		return this.service({ url, params: { ...pramas, ..._object }, method: "GET" })
	}

	post<T, K>(url: string, pramas?: K, _object = {}): Promise<ResultData<T>> {
		return this.service({ url, ...pramas, ..._object, method: "POST" })
	}

	put<T, K>(url: string, pramas?: K, _object = {}): Promise<ResultData<T>> {
		return this.service({ url, ...pramas, ..._object, method: "PUT" })
	}

	delete<T, K>(url: string, pramas?: K, _object = {}): Promise<ResultData<T>> {
		return this.service({ url, params: { ...pramas, ..._object }, method: "DELETE" })
	}
}
export default new HyAxios(config)
